﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using System.Collections.Generic;

public class Characters
{
    public enum States
    {
        Alive,
        TakingDamage,
        Dead
    };

    //protected SpriteEffects flip = SpriteEffects.None;

    protected Animation walkingUpAnimation, walkingDownAnimation, walkingLeftAnimation, walkingRightAnimation;
    protected Animation idleUpAnimation, idleDownAnimation, idleLeftAnimation, idleRightAnimation;
    protected Animation barrelAnimation;
    protected Animation barrelRollingAnimation;
    protected Animation barrelThrowingAnimation;
    protected Animation hitAnimation;
    protected Animation dyingAnimation;
    public AnimationPlayer sprite;

    protected Texture2D testCollider;

    //private Direction direction = Direction.Down;

    protected string tankingDamageSound;

    private int takingDamageTime = 0;
    private int blinkingTime = 0;

    public int Life
    {
        get { return life; }
        set { life = value; }
    }
    private int life;

    public States State
    {
        get { return state; }
        //set { state = value; }
    }
    private States state;

    public Direction _Direction
    {
        get { return direction; }
        set { direction = value; }
    }
    private Direction direction = Direction.Down;

    // Physics state
    protected float Speed
    {
        get { return speed; }
        set { speed = value; }
    }
    private float speed;

    protected float Friction
    {
        get { return friction; }
        set { friction = value; }
    }
    private float friction;

    Texture2D front;
    public Texture2D Front
    {
        get
        {
            return front;
        }
    }

    protected Vector2 origin = Vector2.Zero;
    protected Vector2 position;
    public Vector2 Position
    {
        get
        {
            return position;
        }
        set
        {
            position = value;
        }
    }
    public Vector2 Origin
    {
        get
        {
            return origin;
        }
        set
        {
            position = value;
            origin = value;
        }
    }

    protected Vector2 Velocity;


    protected Rectangle localBounds;
    /// <summary>
    /// Gets a rectangle which bounds this character in world space.
    /// </summary>
    public Rectangle BoundingRectangle
    {
        get
        {
            int left = (int)Math.Round(Position.X - sprite.Origin.X) + localBounds.X;
            int top = (int)Math.Round(Position.Y - sprite.Origin.Y) + localBounds.Y;

            return new Rectangle(left, top, localBounds.Width, localBounds.Height);
        }
    }

    public void CreateAnimation(Texture2D chara)
    {
        int wid = chara.Width / 3;
        int hei = chara.Height / 4;
        int aux = wid * hei;
        List<Color[]> list = new List<Color[]>();
        for (int j = 0; j < 4; j++)
        {
            for (int i = 0; i < 3; i++)
            {
                Color[] color = new Color[aux];
                chara.GetData(0, new Rectangle(wid * i, hei * j, wid, hei), color, 0, aux);
                list.Add(color);
            }
        }

        GraphicsDevice device = ScreenManager.Graphics.GraphicsDevice;

        Texture2D idleup = new Texture2D(device, wid, hei);
        idleup.SetData(list[1]);
        idleUpAnimation = new Animation(idleup, 0.1f, true, 1);

        Texture2D walkup = new Texture2D(device, wid * 2, hei);
        walkup.SetData(0, new Rectangle(0, 0, wid, hei), list[0], 0, aux, SetDataOptions.NoOverwrite);
        walkup.SetData(0, new Rectangle(wid, 0, wid, hei), list[2], 0, aux, SetDataOptions.NoOverwrite);
        walkingUpAnimation = new Animation(walkup, 0.1f, true, 2);

        Texture2D idler = new Texture2D(device, wid, hei);
        idler.SetData(list[4]);
        idleRightAnimation = new Animation(idler, 0.1f, true, 1);

        Texture2D walkr = new Texture2D(device, wid * 2, hei);
        walkr.SetData(0, new Rectangle(0, 0, wid, hei), list[3], 0, aux, SetDataOptions.NoOverwrite);
        walkr.SetData(0, new Rectangle(wid, 0, wid, hei), list[5], 0, aux, SetDataOptions.NoOverwrite);
        walkingRightAnimation = new Animation(walkr, 0.1f, true, 2);

        front = new Texture2D(device, wid, hei);
        front.SetData(list[7]);
        idleDownAnimation = new Animation(front, 0.1f, true, 1);

        Texture2D walkd = new Texture2D(device, wid * 2, hei);
        walkd.SetData(0, new Rectangle(0, 0, wid, hei), list[6], 0, aux, SetDataOptions.NoOverwrite);
        walkd.SetData(0, new Rectangle(wid, 0, wid, hei), list[8], 0, aux, SetDataOptions.NoOverwrite);
        walkingDownAnimation = new Animation(walkd, 0.1f, true, 2);

        Texture2D idlel = new Texture2D(device, wid, hei);
        idlel.SetData(list[10]);
        idleLeftAnimation = new Animation(idlel, 0.1f, true, 1);

        Texture2D walkl = new Texture2D(device, wid * 2, hei);
        walkl.SetData(0, new Rectangle(0, 0, wid, hei), list[9], 0, aux, SetDataOptions.NoOverwrite);
        walkl.SetData(0, new Rectangle(wid, 0, wid, hei), list[11], 0, aux, SetDataOptions.NoOverwrite);
        walkingLeftAnimation = new Animation(walkl, 0.1f, true, 2);

        int width = (int)(idleDownAnimation.FrameWidth * Globals.CollisionWidth);
        int left = (idleDownAnimation.FrameWidth - width) >> 1;
        int height = (int)(idleDownAnimation.FrameHeight * Globals.CollisionHeight) >> 1;
        int top = (idleDownAnimation.FrameHeight - height);
        localBounds = new Rectangle(left, top, width, height);

        sprite.PlayAnimation(idleDownAnimation);
    }

    public Characters(float speed, float friction, Vector2 position)
    {
        state = States.Alive;
        Speed = speed;
        Friction = friction;
        Position = position;

        LoadContent(GameSession.Content);
    }

    public virtual void TakeDamage(int damage)
    {
        if (State == States.Alive)
        {
            Life -= damage;
            state = Life <= 0 ? States.Dead : States.TakingDamage;

            AudioManager.PlaySound(tankingDamageSound);
        }
    }

    /// <summary>
    /// Loads the character sprite sheet and sounds.
    /// </summary>
    public virtual void LoadContent(ContentManager content) 
    {
        
    }

    /// <summary>
    /// Handles input, performs physics, and animates the player sprite.
    /// </summary>
    public virtual void Update(GameTime gameTime)
    {
        //if (Velocity.X > 0)
        //    flip = SpriteEffects.FlipHorizontally;
        //else
        //    flip = SpriteEffects.None;

        if (Velocity.Length() > 0)
        {
            switch (direction)
            {
                case Direction.Up:
                    sprite.PlayAnimation(walkingUpAnimation);
                    break;
                case Direction.Right:
                    sprite.PlayAnimation(walkingRightAnimation);
                    break;
                case Direction.Left:
                    sprite.PlayAnimation(walkingLeftAnimation);
                    break;
                case Direction.Down:
                    sprite.PlayAnimation(walkingDownAnimation);
                    break;
            }
        }
        else
        {
            switch (direction)
            {
                case Direction.Up:
                    sprite.PlayAnimation(idleUpAnimation);
                    break;
                case Direction.Down:
                    sprite.PlayAnimation(idleDownAnimation);
                    break;
                case Direction.Left:
                    sprite.PlayAnimation(idleLeftAnimation);
                    break;
                case Direction.Right:
                    sprite.PlayAnimation(idleRightAnimation);
                    break;
            }
        }

        ApplyPhysics(true);
    }

    /// <summary>
    /// Updates the character's velocity and position.
    /// </summary>
    protected virtual void ApplyPhysics(/*GameTime gameTime*/ bool checkall)
    {
        Vector2 previousPosition = Position;

        // Apply velocity and friction.
        Position += Velocity;

        /*Console.WriteLine("geral " + BoundingRectangle.X + " " + BoundingRectangle.Y);
        if (GameSession.CheckCollision(BoundingRectangle))
        {
            Console.WriteLine("colidiu");
            Position -= Velocity;
            Velocity = Vector2.Zero;
        }*/
        Velocity *= Friction;
    }

    /// <summary>
    /// Draws animated characters.
    /// </summary>
    public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch)
    {
        sprite.Draw(gameTime, spriteBatch, position, SpriteEffects.None);

        //SpriteFont font = GameSession.Content.Load<SpriteFont>("SpriteFont1");

        //spriteBatch.DrawString(font, "|",  new Vector2(BoundingRectangle.X + BoundingRectangle.Width, BoundingRectangle.Y ), Color.White);
        //spriteBatch.DrawString(font, "|",  new Vector2(BoundingRectangle.X, BoundingRectangle.Y ), Color.White);
        //spriteBatch.DrawString(font, "|", new Vector2(BoundingRectangle.X, BoundingRectangle.Y + BoundingRectangle.Height), Color.White);
        //spriteBatch.DrawString(font, "|", new Vector2(BoundingRectangle.X + BoundingRectangle.Width, BoundingRectangle.Y + BoundingRectangle.Height), Color.White);

        //sprite.Draw(gameTime, spriteBatch, new Vector2(Position.X, Position.Y + GameSession.screenAdjustment), flip);

        //Test Bounding Size
        //spriteBatch.Draw(testCollider, new Vector2(BoundingRectangle.X, BoundingRectangle.Y + GameSession.screenAdjustment),
        //  new Rectangle(0, 0, BoundingRectangle.Width, BoundingRectangle.Height), Color.White);
    }

    public void UpdateTexture(Texture2D texture)
    {
        idleDownAnimation = new Animation(texture, 0.1f, false, 1);
        sprite.PlayAnimation(idleDownAnimation);

        int width = (int)(idleDownAnimation.FrameWidth * Globals.CollisionWidth);
        int left = (idleDownAnimation.FrameWidth - width) >> 1;
        int height = (int)(idleDownAnimation.FrameHeight * Globals.CollisionHeight) >> 1;
        int top = (idleDownAnimation.FrameHeight - height);
        localBounds = new Rectangle(left, top, width, height);
    }
}